home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 June: Reference Library / Dev.CD Jun 00 RL Disk 1.toast / pc / technical documentation / develop / develop issue 25 / develop issue 25 code / toolfrontend.sea / ToolFrontEnd / ToolFrontEnd Source / ToolFrontEnd Panel / ToolFrontEndPanel.c / ToolFrontEndPanel.c
Encoding:
C/C++ Source or Header  |  1996-03-04  |  29.5 KB  |  1,127 lines  |  [TEXT/CWIE]

  1. /*
  2.  *  ToolFrontEndPanel.c - ToolServer Front End Drop-In Preferences
  3.  */
  4.  
  5. /* standard headers */
  6. #include <stdarg.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9.  
  10. /* system headers */
  11. #include <AERegistry.h>
  12. #include <Resources.h>
  13. #include <TextUtils.h>
  14. #include <Controls.h>
  15. #include <LowMem.h>
  16. #include <StandardFile.h>
  17. #include <Sound.h>
  18.  
  19. /* compiler headers */
  20. #include <A4Stuff.h>
  21. #include <SetUpA4.h>
  22. #include <DropInPanel.h>
  23.  
  24. /* project headers */
  25. #include "ToolFrontEnd.h"
  26. #include "MoreFilesExtras.h"
  27.  
  28.  
  29. /* current version number for our prefs data */
  30. #define PTOOLFRONTENDVERSION 2
  31.  
  32.  
  33. // comment out this line to enable debugging probes
  34. #define DebugStr(s)
  35.  
  36.  
  37. enum {
  38.     kItemListIDV1 = 128,
  39.     kItemListID = 130,
  40.     kIncludeScannerItem = 1,
  41.     kIncludePathItem = 2,
  42.     kIncludeBoxItem = 5,
  43.     kCommandLabelItem = 6,
  44.     kCommandItem = 7,
  45.     kExtensionPopupItem = 8,
  46.     kScriptIncludeFileItem = 10,
  47.     kOverallBoxItem = 11,
  48.     kImportSettingsItem = 12,
  49.     kGetExtensionDialog = 129,
  50.     kExtensionTextItem = 4
  51. };
  52.  
  53.  
  54. typedef struct
  55. {
  56.     short current;                // current selection in popup menu
  57.     Boolean enableIncludes;        // scan for include files
  58.     Boolean popupsInitialized;    // has the popup been initialized?
  59.     PanelParameterBlock *pb;    // the parameter block
  60. } ToolFrontEndPanelStatus;
  61.  
  62.  
  63. /* prototypes of local functions */
  64. static void*    InitDialog(PanelParameterBlock *pb);
  65. static void        TermDialog(PanelParameterBlock *pb, void *storage);
  66. static OSErr    OptionsToDialog(PanelParameterBlock *pb, Handle options, void *storage);
  67. static short    DialogToOptions(PanelParameterBlock *pb, Handle options, void *storage);
  68. static short    Filter(DialogPtr dp, EventRecord *event, short *itemHit, void *storage);
  69. static void        ItemHit(PanelParameterBlock *pb, void *storage);
  70. static void        Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset);
  71. static short    GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings);
  72. static short    SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings);
  73. static short    GetFactory(Handle settings, DialogPtr dp);
  74. static short    UpdatePref(Handle settings);
  75. static Boolean    ComparePrefs(Handle prefsHand1, Handle prefsHand2);
  76. static pascal void    PanelDrawIncludeBox(DialogPtr dp, short item);
  77. static pascal void    PanelDrawOverallBox(DialogPtr dp, short item);
  78. static Boolean    GetExtensionString(StringPtr extension);
  79. static void        EnableMainItems(PanelParameterBlock *pb);
  80. static void        DisableAllItems(PanelParameterBlock *pb);
  81. static void        EnableIncludeItems(PanelParameterBlock *pb);
  82. static void        DisableIncludeItems(PanelParameterBlock *pb);
  83. static OSErr    DrawCustomItems(PanelParameterBlock *pb);
  84. static void DrawOverallBox(PanelParameterBlock *pb, ToolFrontEndPanelStatus** status);
  85. static void DrawIncludeBox(PanelParameterBlock *pb, ToolFrontEndPanelStatus** status);
  86. static void ImportSettings(PanelParameterBlock *pb, void *storage);
  87.  
  88. static void *theStorage = NULL; // for DrawUserItem
  89.  
  90.  
  91. /*
  92.  *    main    -    entry-point for Drop-In Preferences Panel
  93.  *
  94.  */
  95.  
  96. pascal short main(PanelParameterBlock *pb)
  97. {
  98.     short err = noErr;
  99.     
  100.     EnterCodeResource();
  101.     PrepareCallback();
  102.     
  103.     switch (pb->request)
  104.     {
  105.     case reqInitPanel:
  106.         /* panel has just been loaded into memory */
  107.         theStorage = NULL;
  108.         break;
  109.  
  110.     case reqTermPanel:
  111.         /* panel is about to be unloaded from memory */
  112.         break;
  113.  
  114.     case reqInitDialog:
  115.         /* hook our dialog item list into the preferences dialog */
  116.         theStorage = pb->storage = InitDialog(pb);
  117.         break;
  118.         
  119.     case reqTermDialog:
  120.         /* unhook our dialog item list from the preferences dialog */
  121.         TermDialog(pb, pb->storage);
  122.         break;
  123.     
  124.     case reqPutData:
  125.         /* put the data in the given handle into our dialog items */
  126.         OptionsToDialog(pb, pb->currentPrefs, pb->storage);
  127.         break;
  128.  
  129.     case reqGetData:
  130.         /* fill in the given handle with our dialog items */
  131.         err = DialogToOptions(pb, pb->currentPrefs, pb->storage);
  132.         break;
  133.  
  134.     case reqFilter:
  135.         /* filter an event in the dialog */
  136.         err = Filter(pb->dialog, pb->event, &pb->itemHit, pb->storage);
  137.         break;
  138.         
  139.     case reqItemHit:
  140.         /* handle a hit on one of our dialog items */
  141.         ItemHit(pb, pb->storage);
  142.         break;
  143.         
  144.     case reqAEGetPref:
  145.         /* return one item in the given handle as an Apple Event descriptor */
  146.         err = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
  147.         break;
  148.  
  149.     case reqAESetPref:
  150.         /* change one item in the given handle according to the given Apple Event descriptor */
  151.         err = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
  152.         break;
  153.  
  154.     case reqValidate:
  155.         /* determine if we need to reset paths, recompile, or relink */
  156.         Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset);
  157.         break;
  158.  
  159.     case reqGetFactory:
  160.         /* return our factory settings */
  161.         err = GetFactory(pb->factoryPrefs, pb->dialog);
  162.         break;
  163.  
  164.     case reqUpdatePref:
  165.         /* update the given handle to use the current format for our prefs data */
  166.         err = UpdatePref(pb->currentPrefs);
  167.         break;
  168.     
  169.     case reqDrawCustomItem:
  170.         err = DrawCustomItems(pb);
  171.         break;
  172.         
  173.     default:
  174.         err = paramErr;
  175.         break;
  176.     }
  177.     
  178.     ExitCodeResource();
  179.     
  180.     return err;
  181. }
  182.  
  183.  
  184. /*
  185.  *    PanelDrawOverallBox  -    user item proc to draw box
  186.  */
  187.  
  188. static pascal void PanelDrawOverallBox(DialogPtr dp, short item)
  189. {
  190. #pragma unused (dp, item)
  191.     ToolFrontEndPanelStatus** status;
  192.     
  193.     EnterCallback();
  194.     status = (ToolFrontEndPanelStatus**)theStorage;
  195.     if (status != NULL)
  196.         DrawOverallBox((*status)->pb, status);
  197.     ExitCallback();
  198. }
  199.  
  200.  
  201. static void DrawOverallBox(PanelParameterBlock *pb, ToolFrontEndPanelStatus** status)
  202. {
  203.     Str63 s;
  204.     
  205.     GetIndString(s, 128, 3);
  206.     CWPanlDrawPanelBox(pb, kOverallBoxItem, s);
  207.     
  208.     if ((*status)->current < 0)
  209.     {
  210.         // grey it out -- no extensions yet
  211.         Pattern gray;
  212.         Rect labelRect, itemRect;
  213.         PenState savedPen;
  214.         
  215.         GetPenState(&savedPen);
  216.         PenNormal();
  217.     
  218.         CWPanlGetItemRect(pb, kOverallBoxItem, &itemRect);
  219.         CWPanlGetItemRect(pb, kCommandLabelItem, &labelRect);
  220.         
  221.         GetIndPattern(&gray, sysPatListID, 4);
  222.         PenMode(patBic);
  223.         PenPat(&gray);
  224.         InsetRect(&itemRect, 1, 1);
  225.         itemRect.top = labelRect.top - 1;
  226.         PaintRect(&itemRect);
  227.         
  228.         SetPenState(&savedPen);
  229.     }
  230. }
  231.  
  232.  
  233. /*
  234.  *    PanelDrawIncludeBox  -    user item proc to draw box
  235.  */
  236.  
  237. static pascal void PanelDrawIncludeBox(DialogPtr dp, short item)
  238. {
  239. #pragma unused (dp, item)
  240.     ToolFrontEndPanelStatus** status;
  241.     
  242.     EnterCallback();
  243.     status = (ToolFrontEndPanelStatus**)theStorage;
  244.     if (status != NULL)
  245.         DrawIncludeBox((*status)->pb, status);
  246.     ExitCallback();
  247. }
  248.  
  249.  
  250. static void DrawIncludeBox(PanelParameterBlock *pb, ToolFrontEndPanelStatus** status)
  251. {
  252.     Str63 s;
  253.     
  254.     GetIndString(s, 128, 4);
  255.     CWPanlDrawPanelBox(pb, kIncludeBoxItem, s);
  256.     
  257.     if ((*status)->current >= 0 && !(*status)->enableIncludes)
  258.     {
  259.         // grey it out -- no include options
  260.         Pattern gray;
  261.         Rect itemRect;
  262.         PenState savedPen;
  263.         
  264.         GetPenState(&savedPen);
  265.         PenNormal();
  266.         CWPanlGetItemRect(pb, kIncludeBoxItem, &itemRect);
  267.         GetIndPattern(&gray, sysPatListID, 4);
  268.         PenMode(patBic);
  269.         PenPat(&gray);
  270.         InsetRect(&itemRect, 1, 1);
  271.         PaintRect(&itemRect);
  272.         SetPenState(&savedPen);
  273.     }
  274. }
  275.  
  276.  
  277. /*
  278.  *    InitDialog  -    initialize Dialog Box items for this panel
  279.  *
  280.  */
  281.  
  282. static void *InitDialog(PanelParameterBlock *pb)
  283. {
  284.     ToolFrontEndPanelStatus**    status;
  285.     
  286.     DebugStr("\p InitDialog start");
  287.     
  288.     status = (ToolFrontEndPanelStatus**)NewHandleClear(sizeof(ToolFrontEndPanelStatus));
  289.     (*status)->current = -1;
  290.     (*status)->pb = pb;
  291.     
  292.     CWPanlAppendItems(pb, pb->version < DROPINPANELAPIVERSION_2 ? kItemListIDV1 : kItemListID);
  293.  
  294.     if (pb->version < DROPINPANELAPIVERSION_2)
  295.     {    
  296.         // CW/7 API -- we have to install user item procs ourselves
  297.         CWPanlInstallUserItem(pb, kIncludeBoxItem, PanelDrawIncludeBox);
  298.         CWPanlInstallUserItem(pb, kOverallBoxItem, PanelDrawOverallBox);
  299.     }
  300.     
  301.     // SelectDialogItemText(dp, baseItems + kCommandItem, 0, 32767);
  302.     CWPanlActivateItem(pb, kCommandItem);
  303.     
  304.     return (void*)status;
  305. }
  306.  
  307. /*
  308.  *    TermDialog    -    destroy Dialog Box items for this panel
  309.  *
  310.  */
  311.  
  312. static void TermDialog(PanelParameterBlock *pb, void *storage)
  313. {
  314.     if (storage != NULL)
  315.         DisposeHandle((Handle)storage);
  316.     if (pb->version < DROPINPANELAPIVERSION_2)
  317.     {
  318.         // CW/7 API -- we have to release the memory we allocated in InitDialog
  319.         CWPanlRemoveUserItem(pb, kIncludeBoxItem);
  320.         CWPanlRemoveUserItem(pb, kOverallBoxItem);
  321.     }
  322.     theStorage = NULL;
  323. }
  324.  
  325.  
  326. /*
  327.  *    DrawCustomItems  -    draw user items
  328.  *
  329.  */
  330.  
  331. static OSErr    DrawCustomItems(PanelParameterBlock *pb)
  332. {
  333.     switch (pb->itemHit - pb->baseItems)
  334.     {
  335.     case kIncludeBoxItem:
  336.         DrawIncludeBox(pb, (ToolFrontEndPanelStatus**)pb->storage);
  337.         break;
  338.     case kOverallBoxItem:
  339.         DrawOverallBox(pb, (ToolFrontEndPanelStatus**)pb->storage);
  340.         break;
  341.     }
  342.     return noErr;
  343. }
  344.  
  345.  
  346. /*
  347.  *    OptionsToDialog        -    copy the options data from the handle to the screen
  348.  *
  349.  */
  350.  
  351. static OSErr OptionsToDialog(PanelParameterBlock *pb, Handle options, void *storage)
  352. {
  353.     ToolFrontEndPanelStatus**    status = (ToolFrontEndPanelStatus**)storage;
  354.     ToolFrontEndPrefHandle        prefsData = (ToolFrontEndPrefHandle) options;
  355.     Byte                        state;
  356.     int                            i;
  357.     MenuHandle                    menu;
  358.     ControlHandle                popup;
  359.     Handle                        controlData;
  360.     PopupPrivateDataHandle        popupData;
  361.     OSErr                        err;
  362.  
  363.     DebugStr("\p OptionsToDialog start");
  364.  
  365.     // initialize the popup menus
  366.     if (!(*status)->popupsInitialized)
  367.     {
  368.         // initialize the filename extensions popup
  369.         CWPanlGetItemControl(pb, kExtensionPopupItem, &popup);
  370.         controlData = (*popup)->contrlData;
  371.         popupData = (PopupPrivateDataHandle)controlData;
  372.         menu = (*popupData)->mHandle;
  373.         DisableItem(menu, 2); // disable remove
  374.         while (CountMItems(menu) > 2) DeleteMenuItem(menu, 3);
  375.         SetControlMaximum(popup, 2);
  376.         (*status)->current = -1;
  377.     
  378.         for (i = 0; i < (*prefsData)->numExtensions; i++)
  379.         {
  380.             if (i == 0)
  381.             {
  382.                 AppendMenu(menu, "\p(-");    // separator line
  383.                 EnableItem(menu, 2);        // enable remove
  384.                 (*status)->current = 0;
  385.                 SetControlMaximum(popup, 3);
  386.             }
  387.             
  388.             state = HGetState(options);
  389.             HLock(options);
  390.             AppendMenu(menu, "\pgrog");
  391.             SetMenuItemText(menu, CountMItems(menu), (*prefsData)->extensions[i].extension);
  392.             SetControlMaximum(popup, GetControlMaximum(popup) + 1);
  393.             HSetState(options, state);
  394.             
  395.             if (i == 0)
  396.                 SetControlValue(popup, 4);    // select first extension
  397.         }
  398.         
  399.         // initialize the include file scanner popup
  400.         CWPanlGetItemControl(pb, kIncludeScannerItem, &popup);
  401.         controlData = (*popup)->contrlData;
  402.         popupData = (PopupPrivateDataHandle)controlData;
  403.         menu = (*popupData)->mHandle;
  404.         
  405.         // find the include file scanner folder
  406.         {
  407.             Str31 folderName;
  408.             FCBPBRec pb;
  409.             CInfoPBRec ci;
  410.             FSSpec *scanners;
  411.             short actualCount;
  412.             short index;
  413.             
  414.             pb.ioFCBIndx = 0; // use ioRefNum
  415.             pb.ioRefNum = LMGetCurApRefNum();
  416.             pb.ioNamePtr = NULL;
  417.             err = PBGetFCBInfoSync(&pb);
  418.             if (err != noErr) return err;
  419.             GetIndString(folderName, 128, 1); // CodeWarrior Plugins
  420.             ci.dirInfo.ioNamePtr = folderName;
  421.             ci.dirInfo.ioVRefNum = pb.ioFCBVRefNum;
  422.             ci.dirInfo.ioDrDirID = pb.ioFCBParID;
  423.             ci.dirInfo.ioFDirIndex = 0;
  424.             err = PBGetCatInfoSync(&ci);
  425.             if (err != noErr) return err;
  426.             GetIndString(folderName, 128, 2); // Include Scanners
  427.  
  428.             // iterate over all files in folder, adding to popup menu
  429.             scanners = (FSSpec*)NewPtr(sizeof(FSSpec[100]));
  430.             if (scanners == NULL) return MemError();
  431.             index = 1;
  432.             do
  433.             {
  434.                 short i;
  435.                 err = GetDirItems(pb.ioFCBVRefNum, ci.dirInfo.ioDrDirID, folderName, true, false, scanners, 100, &actualCount, &index);
  436.                 for (i = 0; i < actualCount; i++)
  437.                 {
  438.                     AppendMenu(menu, "\pgrog");
  439.                     SetMenuItemText(menu, CountMItems(menu), scanners[i].name);
  440.                     SetControlMaximum(popup, GetControlMaximum(popup) + 1);
  441.                 }
  442.             } while (err == noErr);
  443.             DisposePtr((Ptr)scanners);
  444.         }
  445.         
  446.         (*status)->popupsInitialized = true;
  447.     }
  448.  
  449.     state = HGetState((Handle)status);
  450.     HLock((Handle)status);
  451.         
  452.     CWPanlSetItemText(pb, kScriptIncludeFileItem, (*prefsData)->scriptIncludeFile);
  453.  
  454.     if ((*status)->current < 0)
  455.     {
  456.         // no current extension -- disable all items
  457.         DisableAllItems(pb);
  458.         (*status)->enableIncludes = false;
  459.     }
  460.     else
  461.     {
  462.         EnableMainItems(pb);
  463.         (*status)->enableIncludes = ((*prefsData)->extensions[(*status)->current].extension[0] != 0);
  464.         if ((*status)->enableIncludes)
  465.             EnableIncludeItems(pb);
  466.         else
  467.             DisableIncludeItems(pb);
  468.         
  469.         // set up scanner popup menu selection
  470.         {
  471.             Str31 theScanner;
  472.             short i, lim;
  473.             
  474.             CWPanlGetItemControl(pb, kIncludeScannerItem, &popup);
  475.             controlData = (*popup)->contrlData;
  476.             popupData = (PopupPrivateDataHandle)controlData;
  477.             menu = (*popupData)->mHandle;
  478.             BlockMoveData((*prefsData)->extensions[(*status)->current].scanner, theScanner,
  479.                           (*prefsData)->extensions[(*status)->current].scanner[0] + 1);
  480.             for (i = 3, lim = CountMItems(menu); i <= lim; i++)
  481.             {
  482.                 // if this is the scanner, then select it
  483.                 Str31 thisScanner;
  484.                 GetMenuItemText(menu, i, thisScanner);
  485.                 if (EqualString(thisScanner, theScanner, false, true))
  486.                 {
  487.                     SetControlValue(popup, i);
  488.                     break;
  489.                 }
  490.             }
  491.         }
  492.         
  493.         CWPanlSetItemText(pb, kIncludePathItem,
  494.                           (*prefsData)->extensions[(*status)->current].includeFileArg);
  495.         CWPanlSetItemText(pb, kCommandItem,
  496.                           (*prefsData)->extensions[(*status)->current].commandTemplate);
  497.     }
  498.     
  499.     HSetState((Handle)status, state);
  500.     DebugStr("\p OptionsToDialog end");
  501.     return noErr;
  502. }
  503.  
  504.  
  505. /*
  506.  *    DialogToOptions        -    copy the options data from screen to the handle
  507.  *
  508.  */
  509.  
  510. static short DialogToOptions(PanelParameterBlock *pb, Handle options, void *storage)
  511. {
  512.     ToolFrontEndPanelStatus**    status = (ToolFrontEndPanelStatus**)storage;
  513.     ToolFrontEndPref **            prefsData = (ToolFrontEndPrefHandle) options;
  514.     Str255                        tempStr;
  515.     Byte                        state;
  516.     MenuHandle                    menu;
  517.     ControlHandle                popup;
  518.     Handle                        controlData;
  519.     PopupPrivateDataHandle        popupData;
  520.     
  521.     DebugStr("\p DialogToOptions start");
  522.     
  523.     state = HGetState((Handle)status);
  524.     HLock((Handle)status);
  525.     
  526.     CWPanlGetItemText(pb, kScriptIncludeFileItem, tempStr, 255);
  527.     if (StrLength(tempStr) >= sizeof((*prefsData)->scriptIncludeFile))
  528.         tempStr[0] = sizeof((*prefsData)->scriptIncludeFile) - 1;
  529.     BlockMoveData(tempStr, (*prefsData)->scriptIncludeFile, StrLength(tempStr)+1);
  530.     
  531.     if ((*status)->current < 0)
  532.     {
  533.         // no current extension
  534.     }
  535.     else
  536.     {
  537.         // extract data from scanner popup menu
  538.         CWPanlGetItemControl(pb, kIncludeScannerItem, &popup);
  539.         controlData = (*popup)->contrlData;
  540.         popupData = (PopupPrivateDataHandle)controlData;
  541.         menu = (*popupData)->mHandle;
  542.         if (GetControlValue(popup) == 1)
  543.         {
  544.             (*prefsData)->extensions[(*status)->current].scanner[0] = 0;
  545.         }
  546.         else if (menu != NULL) // somehow this goes NULL when you switch to another panel ? ! ?
  547.         {
  548.             Str31 scanner;
  549.             GetMenuItemText(menu, GetControlValue(popup), scanner);
  550.             BlockMoveData(scanner, (*prefsData)->extensions[(*status)->current].scanner, StrLength(scanner)+1);
  551.         }
  552.         
  553.         CWPanlGetItemText(pb, kIncludePathItem, tempStr, 255);
  554.         if (StrLength(tempStr) >= sizeof((*prefsData)->extensions[(*status)->current].includeFileArg))
  555.             tempStr[0] = sizeof((*prefsData)->extensions[(*status)->current].includeFileArg) - 1;
  556.         BlockMoveData(tempStr, (*prefsData)->extensions[(*status)->current].includeFileArg, StrLength(tempStr)+1);
  557.         
  558.         CWPanlGetItemText(pb, kCommandItem, tempStr, 255);
  559.         if (StrLength(tempStr) >= sizeof((*prefsData)->extensions[(*status)->current].commandTemplate))
  560.             tempStr[0] = sizeof((*prefsData)->extensions[(*status)->current].commandTemplate) - 1;
  561.         BlockMoveData(tempStr, (*prefsData)->extensions[(*status)->current].commandTemplate, StrLength(tempStr)+1);
  562.     }
  563.     
  564.     HSetState((Handle)status, state);
  565.  
  566.     DebugStr("\p DialogToOptions end");
  567.     return noErr;
  568. }
  569.  
  570. /*
  571.  *    Filter        -    filter an event for the Preferences panel
  572.  *
  573.  */
  574.  
  575. static short Filter(DialogPtr dp, EventRecord *event, short *itemHit, void *storage)
  576. {
  577. #pragma unused(dp, event, itemHit, storage)
  578.     return noErr;
  579. }
  580.  
  581.  
  582. /*
  583.  *    ItemHit        -    handle an itemHit in a Preferences panel
  584.  *
  585.  */
  586.  
  587. static void ItemHit(PanelParameterBlock *pb, void *storage)
  588. {
  589.     short                theItem    = pb->itemHit - pb->baseItems;
  590.     ToolFrontEndPanelStatus** status = (ToolFrontEndPanelStatus**)storage;
  591.     ToolFrontEndPref**    current = (ToolFrontEndPrefHandle) pb->currentPrefs;
  592.     ToolFrontEndPref**    original = (ToolFrontEndPrefHandle) pb->originalPrefs;
  593.     ControlHandle        ctrlHand;
  594.     short                value;
  595.     
  596.     DebugStr("\p ItemHit start -- item number:");
  597.     {
  598.         Str31 s;
  599.         NumToString(theItem, s);
  600.         DebugStr(s);
  601.     }
  602.     
  603.     switch (theItem)
  604.     {
  605.     case kExtensionPopupItem:
  606.         CWPanlGetItemControl(pb, theItem, &ctrlHand);
  607.         value = GetControlValue(ctrlHand);
  608.         switch (value)
  609.         {
  610.         case 1:
  611.             // add new extension
  612.             {
  613.                 Str15 extension;
  614.                 Byte state;
  615.                 Size size;
  616.                 
  617.                 // get the menu
  618.                 Handle controlData = (*ctrlHand)->contrlData;
  619.                 PopupPrivateDataHandle popupData = (PopupPrivateDataHandle)controlData;
  620.                 MenuHandle menu = (*popupData)->mHandle;
  621.                 
  622.                 // put up a dialog asking for an extension string
  623.                 if (!GetExtensionString(extension)) break;
  624.                 
  625.                 // XXX search the existing prefs for the string -- no dupes!
  626.                 
  627.                 // add a new entry at the end of the prefs
  628.                 state = HGetState((Handle)current);
  629.                 HLock((Handle)current);
  630.                 size = GetHandleSize((Handle)current);
  631.                 if (state & 0x4)
  632.                     SetResourceSize((Handle)current, size + sizeof(struct ExtensionEntry[1]));
  633.                 else
  634.                     SetHandleSize((Handle)current, size + sizeof(struct ExtensionEntry[1]));
  635.                 BlockMoveData(extension, 
  636.                                 (*current)->extensions[(*current)->numExtensions].extension,
  637.                                 extension[0] + 1);
  638.                 (*current)->extensions[(*current)->numExtensions].includeFileArg[0] = 0;
  639.                 (*current)->extensions[(*current)->numExtensions].scanner[0] = 0;
  640.                 (*current)->extensions[(*current)->numExtensions].commandTemplate[0] = 0;
  641.                 (*current)->numExtensions++;
  642.                 HSetState((Handle)current, state);
  643.  
  644.                 // add a new item at the end of the menu
  645.                 if ((*current)->numExtensions == 1)
  646.                     AppendMenu(menu, "\p(-");
  647.                 AppendMenu(menu, extension);
  648.                 
  649.                 // set the menu item and current status item
  650.                 (*status)->current = (*current)->numExtensions - 1;
  651.                 SetControlMaximum(ctrlHand, (*current)->numExtensions + 3);
  652.                 SetControlValue(ctrlHand, (*current)->numExtensions + 3);
  653.                 
  654.                 // redraw the dialog
  655.                 EnableMainItems(pb);
  656.                 DisableIncludeItems(pb);
  657.                 (*status)->enableIncludes = false;
  658.                 CWPanlInvalItem(pb, kOverallBoxItem);
  659.                 OptionsToDialog(pb, pb->currentPrefs, storage);
  660.             }
  661.             break;
  662.             
  663.         case 2:
  664.             // remove current extension
  665.             {
  666.                 Byte state;
  667.                 Size size;
  668.                 
  669.                 // get the menu
  670.                 Handle controlData = (*ctrlHand)->contrlData;
  671.                 PopupPrivateDataHandle popupData = (PopupPrivateDataHandle)controlData;
  672.                 MenuHandle menu = (*popupData)->mHandle;
  673.                 
  674.                 // delete the menu item
  675.                 DeleteMenuItem(menu, value);
  676.                 
  677.                 // shift and resize data in the handle
  678.                 --(*current)->numExtensions;
  679.                 if ((*current)->numExtensions != (*status)->current)
  680.                 {
  681.                     // shift back later entries
  682.                     BlockMoveData((*current)->extensions + (*status)->current + 1,
  683.                                   (*current)->extensions + (*status)->current,
  684.                                   sizeof(struct ExtensionEntry[1])
  685.                                       * ((*current)->numExtensions - (*status)->current));
  686.                 }
  687.                 state = HGetState((Handle)current);
  688.                 size = GetHandleSize((Handle)current);
  689.                 if (state & 0x4)
  690.                     SetResourceSize((Handle)current, size - sizeof(struct ExtensionEntry[1]));
  691.                 else
  692.                     SetHandleSize((Handle)current, size - sizeof(struct ExtensionEntry[1]));
  693.                 
  694.                 // set the menu item and current status item
  695.                 if ((*current)->numExtensions == 0)
  696.                 {
  697.                     // last one went away
  698.                     DeleteMenuItem(menu, 3);    // delete separator
  699.                     DisableItem(menu, 2);        // delete remove item
  700.                     SetControlValue(ctrlHand, 1);
  701.                     (*status)->current = -1;
  702.                     
  703.                     // redraw the dialog
  704.                     DisableAllItems(pb);
  705.                     CWPanlInvalItem(pb, kOverallBoxItem);
  706.                 }
  707.                 else
  708.                 {
  709.                     (*status)->current = 0;        // select first item
  710.                     SetControlValue(ctrlHand, 4);
  711.                     
  712.                     // redraw the dialog
  713.                     (*status)->enableIncludes = ((*current)->extensions[(*status)->current].scanner[0] != 0);
  714.                     if ((*status)->enableIncludes)
  715.                         EnableIncludeItems(pb);
  716.                     else
  717.                         DisableIncludeItems(pb);
  718.                     CWPanlInvalItem(pb, kOverallBoxItem);
  719.                 }
  720.                 
  721.                 OptionsToDialog(pb, pb->currentPrefs, storage);
  722.             }
  723.             break;
  724.             
  725.         default:
  726.             // select current extension
  727.             DialogToOptions(pb, pb->currentPrefs, storage);
  728.             (*status)->current = value - 4;
  729.             
  730.             // redraw the dialog
  731.             (*status)->enableIncludes = ((*current)->extensions[(*status)->current].scanner[0] != 0);
  732.             if ((*status)->enableIncludes)
  733.                 EnableIncludeItems(pb);
  734.             else
  735.                 DisableIncludeItems(pb);
  736.             CWPanlInvalItem(pb, kOverallBoxItem);
  737.             OptionsToDialog(pb, pb->currentPrefs, storage);
  738.             break;
  739.         }
  740.         break;
  741.  
  742.     case kImportSettingsItem:
  743.         // import settings from another project file
  744.         ImportSettings(pb, storage);
  745.         break;
  746.         
  747.     default:
  748.         DialogToOptions(pb, pb->currentPrefs, storage);
  749.         break;
  750.     }
  751.     
  752.     pb->canRevert    = !ComparePrefs(pb->originalPrefs, pb->currentPrefs);
  753.     pb->canFactory    = !ComparePrefs(pb->factoryPrefs,  pb->currentPrefs);
  754.     
  755.     DebugStr("\p ItemHit end");
  756. }
  757.  
  758.  
  759. // file filter to excelude open files
  760.  
  761. static pascal Boolean NonOpenFileFilter(CInfoPBPtr info)
  762. {
  763.     return (info->hFileInfo.ioFlAttrib & 0x80) == 0 ? false : true;
  764. }
  765.  
  766.  
  767. /*
  768.  *    ImportSettings    -    import settings from another project file
  769.  *
  770.  */
  771.  
  772. static void ImportSettings(PanelParameterBlock *pb, void *storage)
  773. {
  774.     ToolFrontEndPanelStatus** status = (ToolFrontEndPanelStatus**)storage;
  775.     Handle current = (Handle) pb->currentPrefs;
  776.     OSType types = 'MMPR';
  777.     StandardFileReply reply;
  778.     short resRefNum;
  779.     Handle h;
  780.     long size;
  781.     Byte state;
  782.     
  783.     // select a project file which is not open (that is, not this one....)
  784.     StandardGetFile(NonOpenFileFilter, 1, &types, &reply);
  785.     if (!reply.sfGood) return;
  786.     
  787.     // open the resource file, fetch the resource and close the file
  788.     resRefNum = FSpOpenResFile(&reply.sfFile, fsRdPerm);
  789.     if (resRefNum < 0)
  790.     {
  791.         SysBeep(6);
  792.         return;
  793.     }
  794.     h = Get1NamedResource('pref', "\pToolFrontEnd Panel");
  795.     if (h == NULL)
  796.     {
  797.         CloseResFile(resRefNum);
  798.         SysBeep(6);
  799.         return;
  800.     }
  801.     DetachResource(h);
  802.     CloseResFile(resRefNum);
  803.     
  804.     // set the current preferences to match the resource
  805.     size = GetHandleSize(h);
  806.     state = HGetState(current);
  807.     if (state & 0x4)
  808.         SetResourceSize(current, size);
  809.     else
  810.         SetHandleSize(current, size);
  811.     BlockMoveData(*h, *current, size);
  812.     if (state & 0x4)
  813.         ChangedResource(current);
  814.     DisposeHandle(h);
  815.     
  816.     // update the dialog
  817.     (*status)->popupsInitialized = false;
  818.     CWPanlInvalItem(pb, kOverallBoxItem);
  819.     OptionsToDialog(pb, current, storage);
  820. }
  821.  
  822.  
  823. /*
  824.  *    Validate    -    check if panel's changes require a recompile or relink
  825.  *
  826.  */
  827.  
  828. static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset)
  829. {
  830. #pragma unused(original, current)
  831.     
  832.     // XXX Validate
  833.     *recompile    = false;
  834.     *relink        = false;
  835.     *reset        = false;
  836. }
  837.  
  838. /*
  839.  *    GetPref        -    get a specified Preference setting for an AppleEvent request
  840.  *
  841.  */
  842.  
  843. static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings)
  844. {
  845.     ToolFrontEndPref    prefsData    = ** (ToolFrontEndPrefHandle) settings;
  846.     DescType    anEnum;
  847.     OSErr        err;
  848.     
  849.     switch (keyword)
  850.     {
  851. #if 0
  852.     // XXX get a specified Preference setting for an AppleEvent request
  853.     case prefsTFE_IncludeFile:
  854.         err = AECreateDesc(typeText, (*prefsData)->extensions[(*status)->current].scriptIncludeFile + 1,
  855.                             (*prefsData)->extensions[(*status)->current].scriptIncludeFile[0], prefsDesc);
  856.         break;
  857.         
  858.     case prefsPR_ProjectType:
  859.         switch ((*prefsData)->extensions[(*status)->current].projtype)
  860.         {
  861.         case kProjTypeApplication:    anEnum = enum_Project_Application;        break;
  862.         case kProjTypeLibrary:        anEnum = enum_Project_Library;            break;
  863.         case kProjTypeSharedLib:    anEnum = enum_Project_SharedLibrary;    break;
  864.         case kProjTypeCodeResource:    anEnum = enum_Project_CodeResource;        break;
  865.         case kProjTypeMPWTool:        anEnum = enum_Project_MPWTool;            break;
  866.         default:                    return (paramErr);
  867.         }
  868.         err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc);
  869.         break;
  870.         
  871.     case prefsPR_FileName:
  872.         err = AECreateDesc(typeChar, (*prefsData)->extensions[(*status)->current].outfile+1, StrLength((*prefsData)->extensions[(*status)->current].outfile), prefsDesc);
  873.         break;
  874. #endif
  875.  
  876.     default:
  877.         err = errAECantHandleClass;
  878.         break;
  879.     }
  880.     
  881.     return (err);
  882. }
  883.  
  884. /*
  885.  *    SetPref        -    set a specified Preference setting from an AppleEvent request
  886.  *
  887.  */
  888.  
  889. static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings)
  890. {
  891.     ToolFrontEndPref    prefsData    = ** (ToolFrontEndPrefHandle) settings;
  892.     AEDesc            toDesc    = { typeNull, NULL };
  893.     OSErr            err        = noErr;
  894.     Handle            dataHand;
  895.     Size            textLength;
  896.     DescType        anEnum;
  897.     
  898.     switch (keyword)
  899.     {
  900. #if 0
  901.     // XXX set a specified Preference setting from an AppleEvent request
  902.     case prefsLN_GenerateSymFile:
  903.         if (prefsDesc->descriptorType == typeBoolean)
  904.         {
  905.             dataHand = prefsDesc->dataHandle;
  906.         }
  907.         else
  908.         {
  909.             err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc);
  910.             if (err == noErr)
  911.                 dataHand = toDesc.dataHandle;
  912.         }
  913.         if (err == noErr)
  914.         {
  915.             (*prefsData)->extensions[(*status)->current].linksym = ** (Boolean **) dataHand;
  916.         }
  917.         break;
  918.         
  919.     case prefsPR_ProjectType:
  920.         if (prefsDesc->descriptorType != typeEnumeration)
  921.         {
  922.             err = errAETypeError;
  923.             break;
  924.         }
  925.  
  926.         anEnum = ** (DescType **) prefsDesc->dataHandle;
  927.         
  928.         switch (anEnum)
  929.         {
  930.         case enum_Project_Application:        (*prefsData)->extensions[(*status)->current].projtype = kProjTypeApplication;    break;
  931.         case enum_Project_Library:            (*prefsData)->extensions[(*status)->current].projtype = kProjTypeLibrary;        break;
  932.         case enum_Project_SharedLibrary:    (*prefsData)->extensions[(*status)->current].projtype = kProjTypeSharedLib;    break;
  933.         case enum_Project_CodeResource:        (*prefsData)->extensions[(*status)->current].projtype = kProjTypeCodeResource;    break;
  934.         case enum_Project_MPWTool:            (*prefsData)->extensions[(*status)->current].projtype = kProjTypeMPWTool;        break;
  935.         default:                            return (errAECoercionFail);
  936.         }
  937.         break;
  938.         
  939.     case prefsPR_FileName:
  940.         if (prefsDesc->descriptorType == typeChar)
  941.         {
  942.             dataHand = prefsDesc->dataHandle;
  943.         }
  944.         else
  945.         {
  946.             err = AECoerceDesc(prefsDesc, typeChar, &toDesc);
  947.             if (err == noErr)
  948.                 dataHand = toDesc.dataHandle;
  949.         }
  950.         if (err == noErr)
  951.         {
  952.             textLength = GetHandleSize(dataHand);
  953.             if (textLength > sizeof((*prefsData)->extensions[(*status)->current].outfile) - 1)
  954.                 textLength = sizeof((*prefsData)->extensions[(*status)->current].outfile) - 1;
  955.             BlockMoveData(*dataHand, (*prefsData)->extensions[(*status)->current].outfile+1, textLength);
  956.             (*prefsData)->extensions[(*status)->current].outfile[0] = textLength;
  957.         }
  958.         break;
  959. #endif
  960.  
  961.     default:
  962.         err = errAECantHandleClass;
  963.         break;
  964.     }
  965.     
  966.     if (err == noErr)
  967.     {
  968.         ** (ToolFrontEndPrefHandle) settings = prefsData;
  969.     }
  970.     
  971.     AEDisposeDesc(&toDesc);
  972.     
  973.     return (err);
  974. }
  975.  
  976. /*
  977.  *    GetFactory    -    retrieve factory settings
  978.  *
  979.  */
  980.  
  981. static short GetFactory(Handle settings, DialogPtr dp)
  982. {
  983. #pragma unused(dp)
  984.  
  985.     OSErr err;
  986.     SetHandleSize(settings, sizeof(ToolFrontEndPref));
  987.     err = MemError();
  988.     if (err == noErr)
  989.     {
  990.         int i;
  991.         char *c;
  992.         
  993.         for (i = sizeof(ToolFrontEndPref), c = (char*)*settings; i > 0; i--)
  994.             *c++ = 0;
  995.         (*(ToolFrontEndPref**)settings)->version = PTOOLFRONTENDVERSION;
  996.     }
  997.     return (err);
  998. }
  999.  
  1000. /*
  1001.  *    UpdatePref    -    "upgrade" a pref to the current version
  1002.  *
  1003.  */
  1004.  
  1005. static short UpdatePref(Handle settings)
  1006. {
  1007.     ToolFrontEndPrefHandle    prefsHand    = (ToolFrontEndPrefHandle) settings;
  1008.     OSErr err = noErr;
  1009.     
  1010.     switch ((*prefsHand)->version)
  1011.     {
  1012.     case PTOOLFRONTENDVERSION:
  1013.         break;
  1014.     default:
  1015.         err = kBadPrefVersion;
  1016.         break;
  1017.     }
  1018.     
  1019.     return (err);
  1020. }
  1021.  
  1022.  
  1023. static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2)
  1024. {
  1025.     ToolFrontEndPrefHandle    prefs1    = (ToolFrontEndPrefHandle) prefsHand1;
  1026.     ToolFrontEndPrefHandle    prefs2    = (ToolFrontEndPrefHandle) prefsHand2;
  1027.     Boolean differ = false;
  1028.     Byte state1, state2;
  1029.     
  1030.     state1 = HGetState(prefsHand1);
  1031.     HLock(prefsHand1);
  1032.     state2 = HGetState(prefsHand2);
  1033.     HLock(prefsHand2);
  1034.     
  1035.     if ((*prefs1)->numExtensions != (*prefs2)->numExtensions)
  1036.     {
  1037.         differ = true;
  1038.     }
  1039.     else
  1040.     {
  1041.         int i;
  1042.         differ = EqualString((*prefs1)->scriptIncludeFile, (*prefs2)->scriptIncludeFile, false, true);
  1043.         for (i = 0; !differ && i < (*prefs1)->numExtensions; i++)
  1044.         {
  1045.             differ = (    EqualString((*prefs1)->extensions[i].extension, (*prefs2)->extensions[i].extension, false, true)
  1046.                     &&  EqualString((*prefs1)->extensions[i].scanner, (*prefs2)->extensions[i].scanner, false, true)
  1047.                     &&  EqualString((*prefs1)->extensions[i].includeFileArg, (*prefs2)->extensions[i].includeFileArg, false, true)
  1048.                     &&  EqualString((*prefs1)->extensions[i].commandTemplate, (*prefs2)->extensions[i].commandTemplate, false, true));
  1049.         }
  1050.     }
  1051.     
  1052.     HSetState(prefsHand1, state1);
  1053.     HSetState(prefsHand2, state2);
  1054.     
  1055.     return !differ;
  1056. }
  1057.  
  1058.  
  1059. void EnableMainItems(PanelParameterBlock *pb)
  1060. {
  1061.     DebugStr("\p EnableMainItems start");
  1062.     CWPanlEnableItem(pb, kIncludeScannerItem, true);
  1063.     CWPanlEnableItem(pb, kCommandItem, true);
  1064.     DebugStr("\p EnableMainItems end");
  1065. }
  1066.  
  1067.  
  1068. void EnableIncludeItems(PanelParameterBlock *pb)
  1069. {
  1070.     DebugStr("\p EnableIncludeItems start");
  1071.     CWPanlEnableItem(pb, kIncludeScannerItem, true);
  1072.     CWPanlEnableItem(pb, kCommandItem, true);
  1073.     DebugStr("\p EnableIncludeItems end");
  1074. }
  1075.  
  1076.  
  1077. void DisableAllItems(PanelParameterBlock *pb)
  1078. {
  1079.     DebugStr("\p DisableAllItems start");
  1080.     CWPanlEnableItem(pb, kCommandItem, false);
  1081.     DisableIncludeItems(pb);
  1082.     DebugStr("\p DisableAllItems end");
  1083. }
  1084.  
  1085.  
  1086. void DisableIncludeItems(PanelParameterBlock *pb)
  1087. {
  1088.     DebugStr("\p DisableIncludeItems start");
  1089.     CWPanlEnableItem(pb, kIncludeScannerItem, false);
  1090.     CWPanlEnableItem(pb, kIncludePathItem, false);
  1091.     DebugStr("\p DisableIncludeItems end");
  1092. }
  1093.  
  1094.  
  1095. Boolean    GetExtensionString(StringPtr extension)
  1096. {
  1097.     short                itemHit;
  1098.     short                itemType;
  1099.     Rect                itemRect;
  1100.     Handle                itemHand;
  1101.     Boolean                done, result;
  1102.     
  1103.     DialogPtr dialog = GetNewDialog(kGetExtensionDialog, NULL, (WindowPtr)-1);
  1104.     SelectDialogItemText(dialog, kExtensionTextItem, 0, 32767);
  1105.     done = false;
  1106.     do
  1107.     {
  1108.         ModalDialog(NULL, &itemHit);
  1109.         switch (itemHit)
  1110.         {
  1111.         case ok:
  1112.             GetDialogItem(dialog, kExtensionTextItem, &itemType, &itemHand, &itemRect);
  1113.             GetDialogItemText(itemHand, extension);
  1114.             result = true;
  1115.             done = true;
  1116.             break;
  1117.         case cancel:
  1118.             result = false;
  1119.             done = true;
  1120.             break;
  1121.         }
  1122.     } while (!done);
  1123.     DisposeDialog(dialog);
  1124.         
  1125.     return result;
  1126. }
  1127.